/* 
 * Copyright 2009 Shared Object (www.sharedobject.ch)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package edos.prm.actor;

import java.util.HashSet;
import java.util.Set;

import edos.prm.artifact.Artifact;
import edos.prm.artifact.Attribute;
import edos.prm.engine.PrmSecurityManager;
import edos.prm.project.Topic;
import edos.prm.role.Role;

/**
 * An Actor is a comunity member participating to one or more Projects,
 * having multiple {@code Role}s, {@code Interests} and {@code Experience}.
 * The latter two entities are described by {@code Topic}s.
 * 
 * @version 1.0
 */
public interface Actor extends Artifact {

	public static final Actor ROOT_ACTOR = 
		new PrmActor(
				new
				ContactInformation(new EmailAddress("ciaranbryce@gmail.com"),
						"RootActor"));

	/**
	 * Each actor has interests that link him to a project.
	 * 
	 * @return the set of topics forming the interests of the actor
	 * @throws SecurityException if the call is not made via an Actor activity
	 */
	@Attribute
	public Set<Topic> getInterests();

	/**
	 * Each actor has competence that link him to his experience in a project.
	 * 
	 * @return the set of topics forming the interests of the actor
	 * @throws SecurityException if the call is not made via an Actor activity
	 */
	@Attribute
	public Set<Topic> getExperience();

	/**
	 * An actor has contact information.
	 * 
	 * @return the contact information associated with this actor
	 * @throws SecurityException if the call is not made via an Actor activity
	 */
	public ContactInformation getContactInformation();

	/**
	 * Return the roles associated with this actor
	 * 
	 * @return the actor's set of roles
	 * @throws SecurityException if the call is not made via an Actor activity
	 */
	@Attribute
	public Set<Role> getRoles();

	/**
	 * Default implementation of {@code Actor}
	 */
	final static class PrmActor implements Actor {

		private ContactInformation contactInfo;
		private HashSet<Topic> experience;
		private HashSet<Topic> interests;
		private HashSet<Role> roles;

		public PrmActor(ContactInformation cinfo) {
			this.contactInfo = cinfo;
			this.interests = new HashSet<Topic>();
			for ( Topic t : interests )
				this.interests.add(t);
			this.experience = new HashSet<Topic>();
			for ( Topic t : experience )
				this.experience.add(t);
			roles = new HashSet<Role>();
		}

		public ContactInformation getContactInformation() {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			return contactInfo;
		}

		public void addCompetence(Topic topic) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			experience.add(topic);
		}

		public Set<Topic> getExperience() {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class,
						this.getClass());
			HashSet<Topic> result = new HashSet<Topic>();
			result.addAll(experience);
			return result;
		}

		public Set<Topic> getInterests() {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			HashSet<Topic> result = new HashSet<Topic>();
			result.addAll(interests);
			return result;
		}

		public void addInterest(Topic topic) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			interests.add(topic);
		}

		public void removeInterest(Topic topic) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			this.interests.remove(topic);
		}

		public void removeExperience(Topic topic) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			this.experience.remove(topic);
		}

		public Set<Role> getRoles() {
			HashSet<Role> result = new HashSet<Role>();
			result.addAll(roles);
			return result;
		}

		public void removeRole(Role role) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			roles.remove(role);
		}

		public void addRole(Role role) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			roles.add(role);
		}

		public void setInterests(Topic...topics) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			this.interests = new HashSet<Topic>();
			for ( Topic topic : topics)
				this.interests.add(topic);
		}

		public void setExperience(Topic...topics) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			this.experience = new HashSet<Topic>();
			for ( Topic topic : topics)
				this.experience.add(topic);
		}

		public void setContactInformation(ContactInformation cinfo) {
			PrmSecurityManager psm =
				(PrmSecurityManager)System.getSecurityManager();
			if ( psm != null )
				psm.verifyArtifactContainment(ActorManager.class, this.getClass());
			this.contactInfo = cinfo;
		}
	}
}
